package com.example.testvolication.handler;

import com.example.testvolication.pojo.result.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * 统一异常处理
 * <p>
 * 包含对于注解参数校验的异常处理
 * </p>
 *
 * @author zhangs
 * @date 2022/5/18 11:01
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * <p>
     * 方法参数不合法校验
     * </p>
     *
     * @param ex 异常
     * @return R 返回值
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R methodArgumentNotValidException(MethodArgumentNotValidException ex) {
        R r = R.fail(400, ex.getMessage());
        List<ObjectError> objectErrors = ex.getBindingResult().getAllErrors();
        if (!CollectionUtils.isEmpty(objectErrors)) {
            StringBuilder msgBuilder = new StringBuilder();
            for (ObjectError objectError : objectErrors) {
                msgBuilder.append(objectError.getDefaultMessage()).append(",");
            }
            String errorMessage = msgBuilder.toString();
            if (errorMessage.length() > 1) {
                errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
            }
            r.setMsg(errorMessage);
            log.error("报错:MethodArgumentNotValidException exception! error={}", errorMessage);

        }
        return r;
    }
        /**
         * <p>
         *     捕捉RuntimeException,并统一异常抛出,以及追加日志打印
         * </p>
         * @param ex
         * @return
         */
        @ExceptionHandler(RuntimeException.class)
        public R runtimeException (RuntimeException ex){
            log.error("报错:RuntimeException exception! error={}", ex.getCause());
            return R.fail(400, ex.getMessage());
        }

        /**
         * <p>
         * 违反约束校验
         * </p>
         *
         * @param ex
         * @return
         */
        @ExceptionHandler(value = ConstraintViolationException.class)
        public R constraintViolationExceptionHandler (ConstraintViolationException ex){
            R r = R.fail(400, ex.getMessage());
            Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
            Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
            StringBuilder errorMsg = new StringBuilder();
            while (iterator.hasNext()) {
                ConstraintViolation<?> cvl = iterator.next();
                errorMsg.append(cvl.getMessageTemplate());
                break;
            }
            String msg = errorMsg.toString();
            log.error("报错:ConstraintViolationException exception! error={}", msg);
            r.setMsg(msg);
            return r;
        }


    }
